#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <string>
#include "ikcp.h"
#include "link.h"
#include "GXContext.h"
#include "GXCfunction.h"




#define C_ENV_SHARED_PTR_LEN 512


static GXContext *s_gx = 0;


void** __make_sure_gx_env_get_shared_ptr_exists()
{
	static void** aa = NULL;
	if(NULL == aa){
		int len = sizeof(void*) * C_ENV_SHARED_PTR_LEN;
		aa = (void**)malloc(len);
		memset(aa,0,len);
	}
	return aa;
}

void* gx_env_get_shared_ptr(int index)
{
	if(index<0 || index>=C_ENV_SHARED_PTR_LEN) return NULL;
	
	void** p = __make_sure_gx_env_get_shared_ptr_exists();
	if(NULL == p) return NULL;
	
	return p[index];
}

bool gx_env_set_shared_ptr(int index,void *new_value)
{
	if(index<0 || index>=C_ENV_SHARED_PTR_LEN) return false;
	
	void** p = __make_sure_gx_env_get_shared_ptr_exists();
	if(NULL == p) return false;
	
	p[index] = new_value;
	return true;
}

void gx_set_context(struct GXContext *aa)
{
	s_gx = aa;
}

struct GXContext* gx_get_context()
{
	return s_gx;
}

int __gx_uni_call(lua_State* L);

void gxRegisterCFunctions(lua_State *L)
{
	lua_register(L,"gx_uni_call",__gx_uni_call);
}

int __gx_cur_transaction(lua_State* L)
{
	lua_pushinteger(L, (int)UC_currentTransaction);
	return lua_yield(L, 1);
}

int __gx_uni_call(lua_State* L)
{

	int n = lua_gettop(L);
	if(n < 1) return 0;

	return lua_yield(L, n);
}

int gx_write_here(int c, const char *s, int len){
	if(!s_gx) return -1;

	TransactionContext *tr = s_gx->getTrans(c);
	if(NULL==tr) return -1;

	if(0 == tr->io_type_){
		// it's KCP transaction
		KCPPop *kc = s_gx->getKCPPop(tr->my_creator_);
		if(NULL==kc) return -1;

		return ikcp_send(kc->kcp_, s, len);
	}
	else{
		// it's TCP link
		Link *l = s_gx->getLink(tr->my_creator_);
		if(NULL==l) return -1;

		return __kfifo_put(&l->write_fifo_, (unsigned char*)s,len);
	}
}

int gx_close(int c){
	if(!s_gx) return -1;

	Link *l = s_gx->getLink(c);
	if(!l) return -1;

	s_gx->forceCutLink(l);

	return 0;
}
